﻿// Doc-Encode UTF8-BOM, Space(4), Unix(LF)
#include "himpp_extension.h"
#include "klbmem/klb_mem.h"
#include "klbutil/CMap.hpp"
#include "hiobj.h"
#include "hiobj_in.h"
#include "klbmem/klb_buf.h"
#include <assert.h>


#define HIMPP_EXTENSION_BUF         4096


typedef struct himpp_extension_t_
{
    klb::CMap*  p_reg_map;
    klb_buf_t*  p_tmp_buf[HIMPP_EXTENSION_BUF_COUNT];
}himpp_extension_t;


//////////////////////////////////////////////////////////////////////////

static void* himpp_extension_create(klua_env_t* p_env)
{
    himpp_extension_t* ptr = KLB_MALLOCZ(himpp_extension_t, 1, 0);

    ptr->p_reg_map = new klb::CMap();

    for (int i = 0; i < HIMPP_EXTENSION_BUF_COUNT; i++)
    {
        ptr->p_tmp_buf[i] = klb_buf_malloc(HIMPP_EXTENSION_BUF, false);
    }
    
    return ptr;
}

static void himpp_extension_destroy(void* ptr)
{
    himpp_extension_t* p_ex = (himpp_extension_t*)ptr;

    delete p_ex->p_reg_map;

    for (int i = 0; i < HIMPP_EXTENSION_BUF_COUNT; i++)
    {
        KLB_FREE(p_ex->p_tmp_buf[i]);
    }
    
    KLB_FREE(p_ex);
}

static int himpp_extension_loop_once(void* ptr, klua_env_t* p_env, int64_t last_tc, int64_t now)
{
    himpp_extension_t* p_ex = (himpp_extension_t*)ptr;

    return 0;
}

//////////////////////////////////////////////////////////////////////////

int himpp_ex_add(himpp_extension_t* p_ex, hiobj_reg_t* p_reg)
{
    int size = 0;

    for (; p_reg->p_name != NULL; p_reg++)
    {
        p_ex->p_reg_map->Set(p_reg->p_name, (const char*)p_reg, sizeof(hiobj_reg_t));

        if (size < p_reg->size)
        {
            size = p_reg->size;
        }
    }

    // 扩充临时缓存?
    for (int i = 0; i < HIMPP_EXTENSION_BUF_COUNT; i++)
    {
        if (p_ex->p_tmp_buf[i]->buf_len <= size)
        {
            int total_size = KLB_PADDING_4(size + HIMPP_EXTENSION_BUF);
            KLB_FREE(p_ex->p_tmp_buf[i]);

            p_ex->p_tmp_buf[i] = klb_buf_malloc(total_size, false);
        }
    }

    return 0;
}

hiobj_reg_t* himpp_ex_find(himpp_extension_t* p_ex, const char* p_name)
{
    hiobj_reg_t* p_reg = NULL;
    if (p_name)
    {
        p_reg = (hiobj_reg_t*)p_ex->p_reg_map->GetBuf(p_name, NULL);
    }

    return p_reg;
}

klb_buf_t* himpp_ex_tmp_buf(himpp_extension_t* p_ex, int idx)
{
    assert(NULL != p_ex);
    assert(NULL != p_ex->p_tmp_buf);
    assert(idx < HIMPP_EXTENSION_BUF_COUNT);

    return p_ex->p_tmp_buf[idx];
}

//////////////////////////////////////////////////////////////////////////

static int himpp_ex_register(klua_env_t* p_env)
{
    // 注册
    klua_env_extension_t ex = { 0 };

    ex.cb_create = himpp_extension_create;
    ex.cb_destroy = himpp_extension_destroy;
    ex.cb_loop_once = NULL;

    klua_env_register_extension(p_env, HIMPP_EXTENSION, &ex);


    // 给扩展库添加解析hiobj函数
    himpp_extension_t* p_ex = (himpp_extension_t*)klua_env_get_extension(p_env, HIMPP_EXTENSION);
    load_hiobj_common(p_ex);
    load_hiobj_sys(p_ex);
    load_hiobj_vb(p_ex);
    load_hiobj_isp(p_ex);
    load_hiobj_vi(p_ex);
    load_hiobj_vpss(p_ex);
    load_hiobj_vo(p_ex);
    load_hiobj_venc(p_ex);
    load_hiobj_vdec(p_ex);
    load_hiobj_hdmi(p_ex);
    load_hiobj_region(p_ex);
    load_hiobj_ive(p_ex);

    return 0;
}

//////////////////////////////////////////////////////////////////////////

himpp_extension_t* himpp_ex_get(klua_env_t* p_env)
{
    himpp_extension_t* p_ex = (himpp_extension_t*)klua_env_get_extension(p_env, HIMPP_EXTENSION);
    if (NULL == p_ex)
    {
        himpp_ex_register(p_env);

        p_ex = (himpp_extension_t*)klua_env_get_extension(p_env, HIMPP_EXTENSION);
    }

    return p_ex;
}

himpp_extension_t* himpp_ex_get_by_L(lua_State* L)
{
    return himpp_ex_get(klua_env_get_by_L(L));
}
